package com.frank.oj.manager;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.frank.model.entity.group.Group;
import com.frank.model.entity.user.Role;
import com.frank.model.entity.user.UserInfo;
import com.frank.oj.common.exception.StatusFailException;
import com.frank.oj.common.exception.StatusForbiddenException;
import com.frank.oj.common.exception.StatusSystemErrorException;
import com.frank.oj.constant.Constants;
import com.frank.oj.model.vo.UserRolesVO;
import com.frank.oj.service.entity.common.FileEntityService;
import com.frank.oj.service.entity.group.GroupEntityService;
import com.frank.oj.service.entity.user.UserInfoEntityService;
import com.frank.oj.service.entity.user.UserRoleEntityService;
import com.frank.oj.shiro.AccountProfile;
import com.frank.oj.validator.GroupValidator;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;

/**
 * @author frank
 * @Date 2024/3/28
 */
@Component
@Slf4j(topic = "hcoj")
public class ImageManager {
    @Resource
    private GroupValidator groupValidator;
    @Resource
    private FileEntityService fileEntityService;
    @Resource
    private UserRoleEntityService userRoleEntityService;
    @Resource
    private GroupEntityService groupEntityService;
    @Resource
    private UserInfoEntityService userInfoEntityService;

    @Transactional(rollbackFor = Exception.class)
    public Map<Object, Object> uploadCarouselImg(MultipartFile image) throws StatusFailException, StatusSystemErrorException, StatusForbiddenException {

        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");
        boolean isProblemAdmin = SecurityUtils.getSubject().hasRole("problem_admin");
        boolean isAdmin = SecurityUtils.getSubject().hasRole("admin");

        if (!isRoot && !isProblemAdmin && !isAdmin) {
            throw new StatusForbiddenException("对不起，您无权限操作！");
        }

        if (image == null) {
            throw new StatusFailException("上传的图片文件为空！");
        }

        String suffix = image.getOriginalFilename().substring(image.getOriginalFilename().lastIndexOf(".") + 1);
        if (!"jpg,jpeg,gif,png,webp,jfif,svg".toUpperCase().contains(suffix.toUpperCase())) {
            throw new StatusFailException("请选择jpg,jpeg,gif,png,webp,jfif,svg格式的头像图片！");
        }

        FileUtil.mkdir(Constants.File.HOME_CAROUSEL_FOLDER.getPath());
        String filename = IdUtil.simpleUUID() + "." + suffix;
        try {
            image.transferTo(FileUtil.file(Constants.File.HOME_CAROUSEL_FOLDER.getPath() + File.separator + filename));
        } catch (IOException e) {
            throw new StatusSystemErrorException("服务器异常");
        }

        com.frank.model.entity.common.File imgFile = new com.frank.model.entity.common.File();
        imgFile.setName(filename).setFolderPath(Constants.File.HOME_CAROUSEL_FOLDER.getPath())
                .setFilePath(Constants.File.HOME_CAROUSEL_FOLDER.getPath() + File.separator + filename)
                .setSuffix(suffix)
                .setType("carousel")
                .setUid(userRole.getUid());
        fileEntityService.saveOrUpdate(imgFile);

        return MapUtil.builder()
                .put("id", imgFile.getId())
                .put("url", Constants.File.IMG_API.getPath() + filename)
                .map();
    }

    @Transactional(rollbackFor = Exception.class)
    public Map<Object, Object> uploadAvatar(MultipartFile image) throws StatusFailException, StatusSystemErrorException {
        if (image == null) {
            throw new StatusFailException("上传的图片不能为空！");
        }
        if (image.getSize() > 1024 * 1024 * 3) {
            throw new StatusFailException("上传的图片文件大小不能大于3M！");
        }

        String suffix = image.getOriginalFilename().substring(image.getOriginalFilename().lastIndexOf(".") + 1);
        if (!"jpg,jpeg,gif,png,webp".toUpperCase().contains(suffix.toUpperCase())) {
            throw new StatusFailException("仅支持jpg,jpeg,gif,png,webp格式！");
        }
        FileUtil.mkdir(Constants.File.USER_AVATAR_FOLDER.getPath());
        String filename = IdUtil.simpleUUID() + "." + suffix;

        try {
            image.transferTo(FileUtil.file(Constants.File.USER_AVATAR_FOLDER.getPath() + File.separator + filename));
        } catch (Exception e) {
            throw new StatusSystemErrorException("服务器异常：文件上传失败！");
        }

        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        fileEntityService.updateFileToDeleteByUidAndType(userRole.getUid(), "avatar"); //标记删除的头像

        // 更新用户头像
        LambdaUpdateWrapper<UserInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(UserInfo::getAvatar, Constants.File.IMG_API.getPath() + filename).eq(UserInfo::getUuid, userRole.getUid());
        userInfoEntityService.update(updateWrapper);

        com.frank.model.entity.common.File imgFile = new com.frank.model.entity.common.File();
        imgFile.setName(filename)
                .setFolderPath(Constants.File.USER_AVATAR_FOLDER.getPath())
                .setFilePath(Constants.File.USER_AVATAR_FOLDER.getPath() + File.separator + filename)
                .setSuffix(suffix)
                .setType("avatar")
                .setUid(userRole.getUid());

        fileEntityService.saveOrUpdate(imgFile);

        userRole.setAvatar(Constants.File.IMG_API.getPath() + filename);
        UserRolesVO userRolesVO = userRoleEntityService.getUserRoles(userRole.getUid(), null);

        return MapUtil.builder()
                .put("uid", userRolesVO.getUid())
                .put("username", userRolesVO.getUsername())
                .put("nickname", userRolesVO.getNickname())
                .put("avatar", Constants.File.IMG_API.getPath() + filename)
                .put("email", userRolesVO.getEmail())
                .put("number", userRolesVO.getNumber())
                .put("school", userRolesVO.getSchool())
                .put("course", userRolesVO.getCourse())
                .put("signature", userRolesVO.getSignature())
                .put("realname", userRolesVO.getRealname())
                .put("github", userRolesVO.getGithub())
                .put("blog", userRolesVO.getBlog())
                .put("cfUsername", userRolesVO.getCfUsername())
                .put("roleList", userRolesVO.getRoles().stream().map(Role::getRole))
                .map();
    }

    @Transactional(rollbackFor = Exception.class)
    public Group uploadGroupAvatar(MultipartFile image, Long gid) throws StatusForbiddenException, StatusFailException, StatusSystemErrorException {
        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");

        if (!isRoot && !groupValidator.isGroupRoot(userRole.getUid(), gid)) {
            throw new StatusForbiddenException("对不起，您无权限操作！");
        }

        if (image == null) {
            throw new StatusFailException("上传的头像图片文件不能为空！");
        }
        if (image.getSize() > 1024 * 1024 * 2) {
            throw new StatusFailException("上传的头像图片文件大小不能大于2M！");
        }

        String suffix = image.getOriginalFilename().substring(image.getOriginalFilename().lastIndexOf(".") + 1);
        if (!"jpg,jpeg,gif,png,webp".toUpperCase().contains(suffix.toUpperCase())) {
            throw new StatusFailException("请选择jpg,jpeg,gif,png,webp格式的头像图片！");
        }

        FileUtil.mkdir(Constants.File.GROUP_AVATAR_FOLDER.getPath());

        String filename = IdUtil.simpleUUID() + "." + suffix;
        try {
            image.transferTo(FileUtil.file(Constants.File.GROUP_AVATAR_FOLDER.getPath() + File.separator + filename));
        } catch (Exception e) {
            log.error("头像文件上传异常-------------->", e);
            throw new StatusSystemErrorException("服务器异常：头像上传失败！");
        }

        fileEntityService.updateFileToDeleteByGidAndType(gid, "avatar");

        UpdateWrapper<Group> GroupUpdateWrapper = new UpdateWrapper<>();
        GroupUpdateWrapper.set("avatar", Constants.File.IMG_API.getPath() + filename)
                .eq("id", gid);
        groupEntityService.update(GroupUpdateWrapper);

        com.frank.model.entity.common.File imgFile = new com.frank.model.entity.common.File();
        imgFile.setName(filename).setFolderPath(Constants.File.GROUP_AVATAR_FOLDER.getPath())
                .setFilePath(Constants.File.GROUP_AVATAR_FOLDER.getPath() + File.separator + filename)
                .setSuffix(suffix)
                .setType("avatar")
                .setGid(gid);
        fileEntityService.saveOrUpdate(imgFile);

        return groupEntityService.getById(gid);
    }
}
